using System;
using System.Collections;
using System.Data.SqlClient;
using System.Data;
using System.Diagnostics;
namespace Microsoft.CommerceServer.Catalog.Tools
{
	/// <summary>
	/// This class contains the functionality to store the catalog and
	/// inventory resource properties and also manage the core tool functionality. This class is the single entry point class. 
	/// </summary>
	internal sealed class ResourceContext
	{
		#region Private Fields
		/// <summary>
		/// Stores the catalog database connection string
		/// </summary>
		private string catalogConnectionString = null;

		/// <summary>
		/// Stores the inventory database connection string
		/// </summary>
		private string inventoryConnectionString = null;

		/// <summary>
		/// Stores the f_display_oos_skus inventory resource property
		/// </summary>
		private bool displayOutofStockSkus;

		/// <summary>
		/// Stores the f_display_bo_skus inventory resource property
		/// </summary>
		private bool displayBackorderableSkus;

		/// <summary>
		/// Stores the f_display_preordered_skus inventory resource property
		/// </summary>
		private bool displayPreorderableSkus;

		/// <summary>
		/// Stores the f_floor_is_stockout_threshold inventory resource property
		/// </summary>
		private bool floorIsStockOutThreshold;

		/// <summary>
		/// Stores the f_ignore_missing_skus inventory resource property
		/// </summary>
		private bool treatMissingAsOutOfStock;

		/// <summary>
		/// Stores the i_stock_handling inventory resource property
		/// </summary>
		private short stockHandling;
		#endregion
		#region Private Methods
		/// <summary>
		/// Private Constructor
		/// </summary>
		/// <param name="siteName">The site name. </param>
		/// <param name="ignoreInventorySystem">Flag indicating whether inventory system should be ignored if present.</param>
		private ResourceContext(string siteName, bool ignoreInventorySystem)
		{
			// Validate the site name.
			Validations.ValidateSiteName(siteName);
			Hashtable catalogResourceProperties;
			Hashtable inventoryResourceProperties;
			// Get the catalog and inventory resource properties.
			SiteResourceHelper.GetResourceProperties(siteName, !ignoreInventorySystem, out catalogResourceProperties, out inventoryResourceProperties);
			// Initialize the resource context.
			InitializeContext(catalogResourceProperties, inventoryResourceProperties);
		}

		/// <summary>
		/// Get the catalog and inventory resource properties as required and cache them
		/// </summary>
		/// <param name="catalogResourceProperties">Hashtable containing required catalog resource properties</param>
		/// <param name="inventoryResourceProperties">Hashtable containing required inventory resource properties</param>
		private void InitializeContext(Hashtable catalogResourceProperties, Hashtable inventoryResourceProperties)
		{
			Trace.WriteLine("ResourceContext.InitializeContext: Starting");
			//Get the Catalog Database sql connection string from the ADO connection string stored in the resource properties
			string catalogConnectionString = SqlHelper.SqlADOConnectionStringHack(
				(string)catalogResourceProperties[SiteResourceHelper.ConnectionStringProperty]);
			//Cache the catalog connection string
			this.catalogConnectionString = catalogConnectionString;
            // If the inventoryResourceProperties are specified then cache the inventory resource properties.
            if (inventoryResourceProperties != null)
            {
				//Get the Catalog Database sql connection string from the ADO connection string stored in the resource properties
				string inventoryConnectionString = SqlHelper.SqlADOConnectionStringHack(
					(string)inventoryResourceProperties[SiteResourceHelper.InventoryConnectionStringProperty]);

				//Cache the inventory resource properties
				this.inventoryConnectionString = inventoryConnectionString;
				this.displayOutofStockSkus = displayBackorderableSkus = (bool)inventoryResourceProperties[SiteResourceHelper.DisplayBackOrderableSkus];
				this.displayPreorderableSkus = (bool)inventoryResourceProperties[SiteResourceHelper.DisplayPreOrderableSkus];
				this.displayOutofStockSkus = (bool)inventoryResourceProperties[SiteResourceHelper.DisplayOutOfStockSkus];
				this.floorIsStockOutThreshold = (bool)inventoryResourceProperties[SiteResourceHelper.FloorIsStockOutThreshold];
				this.treatMissingAsOutOfStock = !((bool)inventoryResourceProperties[SiteResourceHelper.IgnoreMissingSkus]);
				this.stockHandling = (short)inventoryResourceProperties[SiteResourceHelper.StockHandling];
				Trace.WriteLine("ResourceContext.InitializeContext: Completed");
            }
		}
		#endregion

		#region Internal Methods
		/// <summary>
		/// Static factory method to create a resource context object.
		/// </summary>
		/// <param name="siteName">>The site name. </param>
		/// <param name="ignoreInventorySystem">Flag indicating whether inventory system should be ignored if present.<</param>
		/// <returns>Created Resource Context object</returns>
		internal static ResourceContext CreateResourceContext(string siteName, bool ignoreInventorySystem)
		{
			return new ResourceContext(siteName, ignoreInventorySystem);
		}

		/// <summary>
		/// Get the required inventory resource related properties using either the cached properties or from user specified input.
		/// </summary>
		/// <param name="filterInventoryOptions">User specified inventory filtering options.</param>
		/// <returns>Object containing all required inventory resource properties</returns>
		internal InventoryIntegrationParameters GetInventoryIntegrationParameters(InventoryFilterOptions inventoryFilterOptions)
        {
			Trace.WriteLine("Starting Get Inventory integration parameters ");
            InventoryIntegrationParameters inventoryIntegrationParameters = new InventoryIntegrationParameters();
            // Check if inventory is enabled 
            inventoryIntegrationParameters.EnableInventory = (inventoryConnectionString != null);
            // If inventory is enabled 
            if (inventoryIntegrationParameters.EnableInventory)
            {
                string inventoryServerName;
                string inventoryDatabaseName;
                // Get the server and dtabase name
                SqlHelper.GetServerAndDatabaseName(new SqlConnection(catalogConnectionString),
					new SqlConnection(inventoryConnectionString), out inventoryServerName, out inventoryDatabaseName);
                inventoryIntegrationParameters.InventoryServerName = inventoryServerName;
                inventoryIntegrationParameters.InventoryDatabaseName = inventoryDatabaseName;

                // Get the useThresholdAsFloor and stockHandling from resource properties
                inventoryIntegrationParameters.UseThresholdAsFloor = this.floorIsStockOutThreshold;
                inventoryIntegrationParameters.StockHandling = this.stockHandling;
                inventoryIntegrationParameters.TreatMissingAsoutOfstock = this.treatMissingAsOutOfStock;
                // If the inventory options were specified  then set the filtering options from the inventoryOptions
				if (inventoryFilterOptions != null)
                {
					inventoryIntegrationParameters.FilterOutOfStockSkus = inventoryFilterOptions.FilterOutOfStockSkus;
					inventoryIntegrationParameters.FilterBackorderableSkus = inventoryFilterOptions.FilterBackorderableSkus;
					inventoryIntegrationParameters.FilterPreorderableSkus = inventoryFilterOptions.FilterPreorderableSkus;
                }
                else
                // Set the filtering options from the site resource properties
                {
                    inventoryIntegrationParameters.FilterOutOfStockSkus = !(this.displayOutofStockSkus);
                    inventoryIntegrationParameters.FilterBackorderableSkus = !(this.displayBackorderableSkus);
                    inventoryIntegrationParameters.FilterPreorderableSkus = !(this.displayPreorderableSkus);
                }
            }
			Trace.WriteLine("Get Inventory Integration parameters completed");
			return inventoryIntegrationParameters;
        }

		/// <summary>
		/// Returns a dataset containing empty categories in the given catalog.
		/// </summary>
		/// <param name="productCatalogName">The catalog name.</param>
		/// <param name="filterInventoryOptions">User specified inventory filtering options.<</param>
		/// <returns>a dataset containing details of empty categories in the given catalog.</returns>
		internal CatalogItemsDataSet GetEmptyCategories(string productCatalogName, InventoryFilterOptions inventoryFilterOptions)
		{
			Trace.WriteLine("ResourceContext.GetEmptyCategories starting");
			InventoryIntegrationParameters inventoryIntegrationParameters = new InventoryIntegrationParameters();
			inventoryIntegrationParameters = GetInventoryIntegrationParameters(inventoryFilterOptions);
			CatalogItemsDataSet dataSet = (CatalogItemsDataSet)SqlHelper.ExecuteDataset(catalogConnectionString, CommandType.StoredProcedure,
				SqlHelper.FilterEmptyCategoriesSpName, new object[10] {
				productCatalogName, inventoryIntegrationParameters.EnableInventory, inventoryIntegrationParameters.InventoryServerName, 
				inventoryIntegrationParameters.InventoryDatabaseName,inventoryIntegrationParameters.FilterOutOfStockSkus, 
				inventoryIntegrationParameters.FilterBackorderableSkus, inventoryIntegrationParameters.FilterPreorderableSkus, 
				inventoryIntegrationParameters.UseThresholdAsFloor, inventoryIntegrationParameters.TreatMissingAsoutOfstock, 
				inventoryIntegrationParameters.StockHandling});
			Trace.WriteLine("ResourceContext.GetEmptyCategories completed");
			return dataSet;
		}
		#endregion
	}
}

	/// <summary>
	/// This class contains all the inventory resource related properties including the inventory server and database names
	/// </summary>
	internal class InventoryIntegrationParameters
    {
        bool enableInventory;
        string inventoryServerName;
        string inventoryDatabaseName;
        bool useThresholdAsFloor;
        bool treatMissingAsOutOfStock;
        short stockHandling;
        bool filterOutOfStockSkus;
        bool filterBackorderableSkus;
        bool filterPreorderableSkus;

        internal bool EnableInventory
        {
            get
            {
                return enableInventory;
            }
            set
            {
                enableInventory = value;
            }
        }
        internal string InventoryServerName
        {
            get
            {
                return inventoryServerName;
            }
            set
            {
                inventoryServerName = value;
            }
        }
        internal string InventoryDatabaseName
        {
            get
            {
                return inventoryDatabaseName;
            }
            set
            {
                inventoryDatabaseName = value;
            }
        }
        internal bool UseThresholdAsFloor
        {
            get
            {
                return useThresholdAsFloor;
            }
            set
            {
                useThresholdAsFloor = value;
            }
        }
        internal bool TreatMissingAsoutOfstock
        {
            get
            {
                return treatMissingAsOutOfStock;
            }
            set
            {
                treatMissingAsOutOfStock = value;
            }
        }
        internal short StockHandling
        {
            get
            {
                return stockHandling;
            }
            set
            {
                stockHandling = value;
            }
        }
        internal bool FilterOutOfStockSkus
        {
            get
            {
                return filterOutOfStockSkus;
            }
            set
            {
                filterOutOfStockSkus = value;
            }
        }
        internal bool FilterBackorderableSkus
        {
            get
            {
                return filterBackorderableSkus;
            }
            set
            {
                filterBackorderableSkus = value;
            }
        }
        internal bool FilterPreorderableSkus
        {
            get
            {
                return filterPreorderableSkus;
            }
            set
            {
                filterPreorderableSkus = value;
            }
        }
    }
